#include "coptional.h"
#include <variant>  // 必须包含，std::variant依赖
#include <unordered_map>
#include <cstring>
#include <cstdio>
#include <new>
#include <memory>
#include <functional>
#include <cstdlib>

// 自定义类型操作注册表
struct CustomTypeOps {
    size_t size;
    void (*copy)(const void* src, void* dest);
    void (*destroy)(void* data);
};

// 全局状态：自定义类型注册表和下一个可用ID
static std::unordered_map<COptionalType, CustomTypeOps> g_type_registry;
static int g_next_custom_type = COPTIONAL_CUSTOM_BASE;  // 用int存储自增ID

// 可选值内部数据存储（支持多种类型）
using OptionalData = std::variant<
    int,
    float,
    double,
    char*,  // 字符串（动态分配）
    std::unique_ptr<void, std::function<void(void*)>>  // 自定义类型
>;

// 不透明结构体的实际实现（必须定义在头文件之后，因为依赖COptionalType）
struct COptional {
    OptionalData data;     // 存储值
    COptionalType type;    // 当前类型（或COPTIONAL_NONE）

    COptional() : type(COPTIONAL_NONE) {}
};

// 获取自定义类型操作
static const CustomTypeOps* get_custom_ops(COptionalType type_id) {
    auto it = g_type_registry.find(type_id);
    return (it != g_type_registry.end()) ? &it->second : nullptr;
}

// 注册自定义类型
extern "C" COptionalType coptional_register_custom_type(
    size_t size,
    void (*copy)(const void* src, void* dest),
    void (*destroy)(void* data)
) {
    if (size == 0 || !copy || !destroy) {
        return COPTIONAL_NONE;  // 无效参数
    }
    COptionalType type_id = static_cast<COptionalType>(g_next_custom_type++);  // 用int自增后转换
    g_type_registry[type_id] = {size, copy, destroy};
    return type_id;
}

// 创建可选值对象
extern "C" COptional* coptional_create(void) {
    try {
        return new COptional();
    } catch (const std::bad_alloc&) {
        return nullptr;
    }
}

// 销毁可选值对象
extern "C" void coptional_destroy(COptional* opt) {
    if (!opt) return;

    // 释放字符串内存
    if (opt->type == COPTIONAL_STR) {
        if (std::holds_alternative<char*>(opt->data)) {
            char* str = std::get<char*>(opt->data);
            free(str);
        }
    }
    // 自定义类型由unique_ptr自动释放
    delete opt;
}

// 清除值（恢复为无值）
extern "C" void coptional_clear(COptional* opt) {
    if (!opt) return;

    // 释放字符串内存
    if (opt->type == COPTIONAL_STR) {
        if (std::holds_alternative<char*>(opt->data)) {
            free(std::get<char*>(opt->data));
        }
    }
    // 重置为无值状态
    opt->type = COPTIONAL_NONE;
}

// 设置整数
extern "C" void coptional_set_int(COptional* opt, int value) {
    if (!opt) return;

    coptional_clear(opt);  // 清除原有值
    opt->data = value;
    opt->type = COPTIONAL_INT;
}

// 设置浮点数
extern "C" void coptional_set_float(COptional* opt, float value) {
    if (!opt) return;

    coptional_clear(opt);
    opt->data = value;
    opt->type = COPTIONAL_FLOAT;
}

// 设置双精度浮点数
extern "C" void coptional_set_double(COptional* opt, double value) {
    if (!opt) return;

    coptional_clear(opt);
    opt->data = value;
    opt->type = COPTIONAL_DOUBLE;
}

// 设置字符串
extern "C" void coptional_set_str(COptional* opt, const char* value) {
    if (!opt) return;

    coptional_clear(opt);  // 释放原有字符串

    if (value) {
        // 复制字符串（动态分配）
        char* str = (char*)malloc(strlen(value) + 1);
        if (str) {
            strcpy(str, value);
            opt->data = str;
            opt->type = COPTIONAL_STR;
            return;
        }
    }
    // 空字符串处理
    opt->data = (char*)nullptr;
    opt->type = COPTIONAL_STR;
}

// 设置自定义类型
extern "C" int coptional_set_custom(COptional* opt, COptionalType type_id, const void* data) {
    if (!opt || !data || type_id < COPTIONAL_CUSTOM_BASE) {
        return -1;
    }

    coptional_clear(opt);  // 清除原有值

    const auto* ops = get_custom_ops(type_id);
    if (!ops) {
        return -1;  // 未注册的类型
    }

    // 分配内存并复制数据
    void* storage = malloc(ops->size);
    if (!storage) {
        return -1;  // 内存分配失败
    }
    ops->copy(data, storage);

    // 存储数据并设置销毁器
    opt->data = std::unique_ptr<void, std::function<void(void*)>>(
        storage,
        [type_id](void* ptr) {
            const auto* ops = get_custom_ops(type_id);
            if (ops) {
                ops->destroy(ptr);  // 调用自定义销毁函数
            }
            free(ptr);  // 释放内存
        }
    );
    opt->type = type_id;
    return 0;
}

// 检查是否有值
extern "C" int coptional_has_value(const COptional* opt) {
    return (opt && opt->type != COPTIONAL_NONE) ? 1 : 0;
}

// 获取值类型
extern "C" COptionalType coptional_get_type(const COptional* opt) {
    return opt ? opt->type : COPTIONAL_NONE;
}

// 获取整数（无值时返回默认值）
extern "C" int coptional_get_int(const COptional* opt, int default_val) {
    if (opt && opt->type == COPTIONAL_INT && std::holds_alternative<int>(opt->data)) {
        return std::get<int>(opt->data);
    }
    return default_val;  // 无值或类型不匹配，返回默认值
}

// 获取浮点数
extern "C" float coptional_get_float(const COptional* opt, float default_val) {
    if (opt && opt->type == COPTIONAL_FLOAT && std::holds_alternative<float>(opt->data)) {
        return std::get<float>(opt->data);
    }
    return default_val;
}

// 获取双精度浮点数
extern "C" double coptional_get_double(const COptional* opt, double default_val) {
    if (opt && opt->type == COPTIONAL_DOUBLE && std::holds_alternative<double>(opt->data)) {
        return std::get<double>(opt->data);
    }
    return default_val;
}

// 获取字符串
extern "C" const char* coptional_get_str(const COptional* opt, const char* default_val) {
    if (opt && opt->type == COPTIONAL_STR && std::holds_alternative<char*>(opt->data)) {
        char* str = std::get<char*>(opt->data);
        return str ? str : default_val;
    }
    return default_val;
}

// 获取自定义类型
extern "C" int coptional_get_custom(const COptional* opt, void* dest) {
    if (!opt || !dest || opt->type < COPTIONAL_CUSTOM_BASE) {
        return -1;
    }

    const auto* ops = get_custom_ops(opt->type);
    if (!ops) {
        return -1;
    }

    if (std::holds_alternative<std::unique_ptr<void, std::function<void(void*)>>>(opt->data)) {
        const void* src = std::get<std::unique_ptr<void, std::function<void(void*)>>>(opt->data).get();
        ops->copy(src, dest);  // 使用注册的复制函数
        return 0;
    }
    return -1;
}